package CRESTAURANT;

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;

/**
 * Class to show lists of data in the user interface
 */
public class PrintList {

    // List labels
    private String[] labels;

    // List columns widths
    private int[] size;

    // Name of the attributes of the Bean with the data
    private String[] attributes;

    // Used for writing
    private PrintWriter out = null;

    /**
     * Default constructor
     */
    public PrintList() {
        String encoding = System.getProperty("file.encoding");
        setPrintWriter(encoding);
        //setPrintWriter( "cp1252" );
    }

    /**
     * Writes the list header
     */
    public void printHeader() {
        StringBuffer head = new StringBuffer();
        StringBuffer line = new StringBuffer();

        for (int i = 0; i < labels.length; i++) {
            head.append(Utilities.trim(this.labels[i], this.size[i],
                    Utilities.LEFT));
            head.append(" ");
            for (int j=0;j<size[i];j++)
                line.append("=");
            line.append(" ");
        }
        out.println(head.toString());
        out.println(line.toString());
    }

    /**
     * Writes one line of the list
     * @param bean Element to be written
     * @param attributes List of attributes
     */
    public void printLine(Object bean, String[] attributes) {
        Method method = null;
        Object value = null;
        int align;
        Class<? extends Object> beanClass = bean.getClass();
        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < attributes.length; i++) {
            try {
                method = beanClass.getMethod("get"
                        + Utilities.capitalize(attributes[i]), new Class[0]);
            } catch (SecurityException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }

            try {
                value = method.invoke(bean, new Object[0]);
            } catch (IllegalArgumentException e1) {
                e1.printStackTrace();
            } catch (IllegalAccessException e1) {
                e1.printStackTrace();
            } catch (InvocationTargetException e1) {
                e1.printStackTrace();
            }

            align = (value instanceof Integer) ? Utilities.RIGHT
                    : Utilities.LEFT;

            sb.append(Utilities.trim(value.toString(), size[i], align));
            sb.append(" ");
        }

        out.println(sb.toString());
    }

    /**
     * Finalizes the list
     */
    public void printEnding() {
        out.flush();
    }

    /**
     * Shows the list on the screen
     * @param list List to be shown
     * @return Indicates if the list to be shown was empty
     */
    public boolean printList(List<? extends Object> list) {
    	boolean empty = true;
        Iterator<? extends Object> it = list.iterator();
        if (it.hasNext()) {
        	empty = false;
            printHeader();
	        do {
	            Object obj = it.next();
	            printLine(obj, attributes);
	        } while (it.hasNext());
	        printEnding();
        }
        return empty;
    }

 
    /**
     * Sets the printWriter that is going to be use to print on the screen.
     * @param codepage Code to apply
     */
    public void setPrintWriter(String codepage) {
        OutputStreamWriter osw = null;
        try {
            osw = new OutputStreamWriter(System.out, codepage);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        out = new PrintWriter(osw);
    }

	/**
	 * @return the labels
	 */
	public String[] getLabels() {
		return labels;
	}

	/**
	 * @param labels the labels to set
	 */
	public void setLabels(String[] labels) {
		this.labels = labels;
	}

	/**
	 * @return the attributes
	 */
	public String[] getAttributes() {
		return attributes;
	}

	/**
	 * @param attributes the attributes to set
	 */
	public void setAttributes(String[] attributes) {
		this.attributes = attributes;
	}

	/**
	 * @return the out
	 */
	public PrintWriter getOut() {
		return out;
	}

	/**
	 * @param out the out to set
	 */
	public void setOut(PrintWriter out) {
		this.out = out;
	}

	/**
	 * @return the size
	 */
	public int[] getSize() {
		return size;
	}
	
	/**
     * @param size Sets a value <code>size</code> to each of the list columns
     */
    public void setSize(int[] size) {
        int[] aux = size;

        // If labels were already assigned, each column width is corrected,
        // to ensure there is enough space to print them correctly
        if ((labels != null) && (labels.length == size.length)) {
            for (int i = 0; i < labels.length; i++) {
                if (size[i] < labels[i].length()) {
                    aux[i] = labels[i].length();
                }
            }
        }

        this.size = aux;
    }

}
